package postgres

import (
	"context"
	"gorm.io/gorm"
	"manager/model"
	"manager/model/entity"
)

var UserEbike = &userEbike{}

type userEbike struct{}

func (a *userEbike) Create(ctx context.Context, m *entity.UserEbike) (int64, error) {
	err := dbWithContext(ctx).Create(m).Error
	return m.ID, err
}
func (a *userEbike) ExecTx(ctx context.Context, fn func(ctx context.Context) error) error {
	return dbWithContext(ctx).Transaction(func(tx *gorm.DB) error {
		ctx = context.WithValue(ctx, contextTxKey{}, tx)
		return fn(ctx)
	})
}

func (a *userEbike) Find(ctx context.Context, id int64) (*entity.UserEbike, error) {
	e := &entity.UserEbike{}
	err := dbWithContext(ctx).Model(&entity.UserEbike{}).Find(&e, id).Error
	return e, err
}

func (a *userEbike) Update(ctx context.Context, id int64, dict map[string]interface{}) error {
	return dbWithContext(ctx).Model(&entity.UserEbike{}).Where("id = ?", id).Updates(dict).Error
}

func (a *userEbike) Delete(ctx context.Context, id int64) error {
	return dbWithContext(ctx).Delete(&entity.UserEbike{}, id).Error
}

func (a *userEbike) List(ctx context.Context, in *model.UserEbikeListRequest) (int, []*entity.UserEbike, error) {
	var (
		q          = dbWithContext(ctx).Model(&entity.UserEbike{})
		err        error
		total      int64
		userEbikes []*entity.UserEbike
	)

	if in.UserID != nil {
		q = q.Where("user_id = ?", *in.UserID)
	}
	if in.EbikeID != nil {
		q = q.Where("ebike_id = ?", *in.EbikeID)
	}
	if in.IsManager != nil {
		q = q.Where("is_manager = ?", *in.IsManager)
	}
	if err = q.Count(&total).Error; err != nil {
		return 0, nil, err
	}
	if err = q.Order("created_at desc").Limit(in.Size).Offset((in.Index - 1) * in.Size).Find(&userEbikes).Error; err != nil {
		return 0, nil, err
	}
	return int(total), userEbikes, nil
}

func (a *userEbike) FindByParameter(ctx context.Context, info *model.UserEbikeRequest) (*entity.UserEbike, error) {
	var (
		err error
		out entity.UserEbike
		q   = dbWithContext(ctx).Model(&entity.UserEbike{})
	)

	if info.UserID != nil {
		q = q.Where("user_id = ?", *info.UserID)
	}
	if info.EbikeID != nil {
		q = q.Where("ebike_id = ?", *info.EbikeID)
	}
	if info.IsManager != nil {
		q = q.Where("is_manager = ?", *info.IsManager)
	}

	err = q.First(&out).Error
	return &out, err
}

func (a *userEbike) FindBikeAndUserBike(ctx context.Context, info *model.UserEbikeAndEbikeInfo) (*model.UserEbikeAndEbikeResponse, error) {
	var (
		err error
		out model.UserEbikeAndEbikeResponse
	)
	str := "select * from ebikes e,user_ebikes ue where  e.id = ? and  ue.user_id = ? and ue.ebike_id = ?"
	err = dbWithContext(ctx).Raw(str, info.EbikeID, info.UserID, info.EbikeID).First(&out).Error

	return &out, err
}

func (a *userEbike) FindCountByIds(ctx context.Context, ids []int64) ([]*model.FindCountByIdsResponse, error) {
	var (
		err error
		q   = dbWithContext(ctx).Model(&entity.UserEbike{})
		out = make([]*model.FindCountByIdsResponse, 0)
	)

	sqlStr := "select user_id id,count(user_id) count from user_ebikes where user_id in (?) group by user_id"
	err = q.Raw(sqlStr, ids).Find(&out).Error

	return out, err
}
